/****************************************************
	文件：StrategyPattern.cs
	作者：HuskyT
	邮箱：1005240602@qq.com
	日期：2020/5/3 17:54:13
	功能：策略模式
*****************************************************/

using System;
using UnityEngine;

namespace DesignPatterns
{
    public class StrategyPattern : MonoBehaviour
    {
        private void Start()
        {
            //策略模式：
            //将算法策略封装起来，集中管理，便于复用，降低业务逻辑和算法之间的耦合度。
            //使用场景：
            //eg：当计算角色受到的伤害 有多种计算策略的时候，使用策略模式
            //       将不同策略单独封装
            //       将计算策略注入到 Context 中，业务逻辑只与 Context 耦合。

            CharacterAttributes player = new CharacterAttributes { Atk = 10, Def = 4, Pierce = 6 };//玩家
            CharacterAttributes enemy = new CharacterAttributes { Atk = 6, Def = 3, Pierce = 4 };//敌人
            //计算玩家攻击敌人造成的伤害：
            //使用伤害计算策略A：
            CalcuDamageContext context = new CalcuDamageContext(new CalcuDamageStrategyA());//注入 策略 到Context中
            float damageA = context.GetResult(player, enemy);
            Debug.LogFormat("使用伤害计算策略A，计算玩家对敌人造成伤害为：{0}", damageA);

            //使用伤害计算策略B：
            context = new CalcuDamageContext(new CalcuDamageStrategyB());//注入 策略 到Context中
            float damageB = context.GetResult(player, enemy);
            Debug.LogFormat("使用伤害计算策略B，计算玩家对敌人造成伤害为：{0}", damageB);
        }

        /// <summary>
        /// 伤害策略计算的上下文
        /// </summary>
        public class CalcuDamageContext
        {
            private StrategyBase<CharacterAttributes, float> mStrategy;
            public CalcuDamageContext(StrategyBase<CharacterAttributes, float> strategy)
            {
                mStrategy = strategy;
            }
            public float GetResult(params CharacterAttributes[] args)
            {
                return mStrategy.GetResult(args);
            }
        }

        /// <summary>
        /// 策略基类
        /// </summary>
        public abstract class StrategyBase<T, TResult>
        {
            public abstract TResult GetResult(params T[] args);
        }
        /// <summary>
        /// 计算伤害（策略A）
        /// </summary>
        public class CalcuDamageStrategyA : StrategyBase<CharacterAttributes, float>
        {
            public override float GetResult(params CharacterAttributes[] args)
            {
                if (args.Length <= 1) return 0.0f;
                CharacterAttributes attacker = args[0];
                CharacterAttributes defender = args[1];
                float damage = attacker.Atk - defender.Def + attacker.Pierce * 0.5f;
                return damage;
            }
        }
        /// <summary>
        /// 计算伤害（策略B）
        /// </summary>
        public class CalcuDamageStrategyB : StrategyBase<CharacterAttributes, float>
        {
            public override float GetResult(params CharacterAttributes[] args)
            {
                if (args.Length <= 1) return 0.0f;
                CharacterAttributes attacker = args[0];
                CharacterAttributes defender = args[1];
                float damage = attacker.Atk - defender.Def + attacker.Pierce;
                return damage;
            }
        }

        /// <summary>
        /// 角色属性
        /// </summary>
        public class CharacterAttributes
        {
            public float Atk;
            public float Def;
            public float Pierce;//穿刺伤害
        }
    }
}